import path from 'path';
import fs from 'fs';

const runCallback = (callback, ok, src, dest, error) => {
  if (typeof callback === 'function') {
    callback({ ok, src, dest, error });
  }
};

export const copy = (src, dest, callback) => {
  try {
    fs.stat(src, (err, stat) => {
      if (err) {
        runCallback(callback, false, src, dest, err);
        return;
      }
      if (stat.isFile()) {
        // 文件，直接复制
        // fs.createReadStream(src).pipe(fs.createWriteStream(dest));
        fs.copyFile(src, dest, fs.constants.COPYFILE_EXCL, (err) => {
          if (!err) {
            runCallback(callback, true, src, dest);
          }
        });
      } else if (stat.isDirectory()) {
        fs.access(dest, (err) => {
          if (err) {
            // 若目标目录不存在，则创建
            fs.mkdirSync(dest, { recursive: true });
          }
          fs.readdir(src, (err, list) => {
            if (err) {
              runCallback(callback, false, src, dest, err);
              return;
            }
            list.forEach((item) => {
              const curSrc = path.resolve(src, item);
              const curDest = path.resolve(dest, item);
              copy(curSrc, curDest, callback);
            });
          });
        });
      }
    });
  } catch (err) {
    runCallback(callback, false, src, dest, err);
  }
};

export default function VitePluginCopy(options) {
  const opt = {
    verbose: true,
    hook: 'closeBundle', // options, closeBundle
    targets: [], // [{ src: "", dest: "" }]
  };
  options = Object.assign(opt, options);
  return {
    name: 'vite-plugin-copy',
    [options.hook]: () => {
      const { verbose, targets } = options;
      if (Array.isArray(targets) && targets.length) {
        targets.forEach(({ src, dest }) => {
          copy(src, dest, ({ ok, src, dest, error }) => {
            if (verbose !== false) {
              if (ok) {
                console.log('copy end: ', src, '--->', dest);
              } else {
                console.error('copy error: ', src, '--->', dest, ':', error);
              }
            }
          });
        });
      }
    },
  };
}
